#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <ifaddrs.h>
#include "cJSON.h"
char *get_local_ip();
/*
    服务器启动开始udp服务器接收客户端的广播，并发送tcp服务器的ip和端口号。使用json发送

 */
int udpServerInit()
{
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
    if (sockfd < 0) {  
        perror("socket err");  
        return -1;  
    }  
  
    struct sockaddr_in saddr;  
    memset(&saddr, 0, sizeof(saddr));  
    saddr.sin_family = AF_INET;  
    saddr.sin_port = htons(6667);  
    saddr.sin_addr.s_addr = INADDR_ANY;  
  
    int broadcast = 1;  
    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof broadcast) < 0) {  
        perror("setsockopt (SO_BROADCAST) failed");  
        close(sockfd);  
        return -1;  
    }  
  
    if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {  
        perror("bind err");  
        close(sockfd);  
        return -1;  
    }  
  
    printf("udp bind succ\n");  
  
    char buf[1024] = {0};  
    struct sockaddr_in caddr;  
    socklen_t len = sizeof(caddr);  
  
    char *local_ip = get_local_ip();  
    if (local_ip == NULL) {  
        perror("Failed to get local IP");  
        close(sockfd);  
        return -1;  
    }  
    printf("%s\n", local_ip);  
  
    while (1) {  
        printf("recvfrom \n");  
        ssize_t n = recvfrom(sockfd, buf, sizeof(buf) - 1, 0, (struct sockaddr *)&caddr, &len);  
        if (n < 0) {  
            perror("udp recvfrom err");  
            break;  
        }  
        buf[n] = '\0'; // 确保字符串以null结尾  
        printf("%s\n", buf);
        cJSON *sendRoot = cJSON_Parse(buf);  
        if (!sendRoot) {  
            printf("Invalid JSON received\n");  
            continue;  
        }  
  
        cJSON *type = cJSON_GetObjectItem(sendRoot, "type");  
        if (type && strcmp(type->valuestring, "device search") == 0) {  
            cJSON *replyRoot = cJSON_CreateObject();  
            cJSON_AddItemToObject(replyRoot, "type", cJSON_CreateString("device search server"));  
            cJSON_AddItemToObject(replyRoot, "ip", cJSON_CreateString(local_ip));  
            cJSON_AddItemToObject(replyRoot, "port", cJSON_CreateNumber(8088));  
            char *reply = cJSON_Print(replyRoot);  
            if (reply == NULL) {  
                perror("cJSON_Print failed");  
                cJSON_Delete(replyRoot);  
                cJSON_Delete(sendRoot);  
                continue;  
            }  
            printf("%s\n", reply);  
            if (sendto(sockfd, reply, strlen(reply), 0, (struct sockaddr *)&caddr, len) < 0) {  
                perror("sendto err");  
            }  
            free(reply); // 释放cJSON_Print分配的内存  
        }  
  
        cJSON_Delete(sendRoot); // 释放cJSON_Parse分配的内存  
    }  
  
    free(local_ip); // 释放get_local_ip分配的内存  
    close(sockfd);
    return 0;
}
// 获取本机IP地址（IPv4）
char *get_local_ip()
{
    struct ifaddrs *ifAddrStruct = NULL;
    char *ip = NULL;
    void *tmpAddrPtr = NULL;

    getifaddrs(&ifAddrStruct);

    for (struct ifaddrs *ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
    {
        if (strcmp(ifa->ifa_name, "ens33") != 0)
        {
            continue;
        }
        tmpAddrPtr = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
        char addressBuffer[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
        if (strcmp(addressBuffer, "127.0.0.1") == 0 || strcmp(addressBuffer, "0.0.0.0") == 0)
        {
            continue;
        }
        ip = strdup(addressBuffer); // 复制地址字符串
    }

    if (ifAddrStruct != NULL)
        freeifaddrs(ifAddrStruct);

    return ip;
}